// 4K Rhythm Game - 核心游戏逻辑
class RhythmGame {
    constructor() {
        this.canvas = document.getElementById('gameCanvas');
        this.ctx = this.canvas.getContext('2d');

        // 游戏配置
        this.config = {
            lanes: 4,
            laneWidth: 100,
            noteHeight: 20,
            noteSpeed: 400, // 增加速度：每秒下降400像素
            judgmentLineY: 550,
            keys: ['d', 'f', 'j', 'k'],
            judgmentWindows: {
                perfect: 40,
                great: 80,
                good: 120
            }
        };

        // 游戏状态
        this.state = {
            isPlaying: false,
            isPaused: false,
            score: 0,
            combo: 0,
            maxCombo: 0,
            accuracy: 100,
            judgments: { perfect: 0, great: 0, good: 0, miss: 0 }
        };

        // 游戏数据
        this.chart = null;
        this.audio = null;
        this.notes = [];
        this.currentTime = 0;
        this.noteIndex = 0;
        this.speedMultiplier = 1.0;

        // 视觉效果
        this.laneEffects = [false, false, false, false];
        this.particles = [];

        // Drag音符状态跟踪
        this.keyPressed = [false, false, false, false];
        this.activeDrags = []; // 存储正在进行的Drag音符

        // 皮肤配置
        this.noteSkin = 'bar'; // 默认皮肤: 'bar', 'circle', 'arrow'

        // 服务器乐曲管理
        this.serverSongs = [];
        this.selectedSong = null;
        this.apiBaseUrl = '/game/api';

        this.init();
    }

    init() {
        this.setupCanvas();
        this.setupEventListeners();
        this.loadSongList(); // 自动加载乐曲列表
        this.render();
    }

    setupCanvas() {
        const width = this.config.lanes * this.config.laneWidth;
        const height = 600;
        this.canvas.width = width;
        this.canvas.height = height;
    }

    setupEventListeners() {
        // 服务器乐曲选择
        document.getElementById('songSelect').addEventListener('change', (e) => this.selectSong(e));
        document.getElementById('refreshSongsBtn').addEventListener('click', () => this.loadSongList());

        // 文件上传（本地）
        document.getElementById('chartFile').addEventListener('change', (e) => this.loadChart(e));
        document.getElementById('audioFile').addEventListener('change', (e) => this.loadAudio(e));

        // 控制按钮
        document.getElementById('startBtn').addEventListener('click', () => this.start());
        document.getElementById('pauseBtn').addEventListener('click', () => this.togglePause());
        document.getElementById('resetBtn').addEventListener('click', () => this.reset());

        // 速度滑块
        document.getElementById('speedSlider').addEventListener('input', (e) => {
            this.speedMultiplier = parseFloat(e.target.value);
            document.getElementById('speedValue').textContent = this.speedMultiplier.toFixed(1);
        });

        // 皮肤选择
        document.getElementById('skinSelect').addEventListener('change', (e) => {
            this.noteSkin = e.target.value;
            console.log('皮肤切换为:', this.noteSkin);
        });

        // 键盘输入
        document.addEventListener('keydown', (e) => this.handleKeyDown(e));
        document.addEventListener('keyup', (e) => this.handleKeyUp(e));
    }

    loadChart(event) {
        const file = event.target.files[0];
        if (!file) return;

        const reader = new FileReader();
        reader.onload = (e) => {
            try {
                this.chart = JSON.parse(e.target.result);
                console.log('谱面加载成功:', this.chart.metadata.title);
                this.showMessage('谱面加载成功！');
            } catch (error) {
                console.error('谱面解析失败:', error);
                this.showMessage('谱面解析失败！', 'error');
            }
        };
        reader.readAsText(file);
    }

    loadAudio(event) {
        const file = event.target.files[0];
        if (!file) return;

        const url = URL.createObjectURL(file);
        this.audio = new Audio(url);
        this.audio.addEventListener('loadeddata', () => {
            console.log('音频加载成功');
            this.showMessage('音频加载成功！');
        });
    }

    start() {
        if (!this.chart) {
            this.showMessage('请先加载谱面文件！', 'error');
            return;
        }
        if (!this.audio) {
            this.showMessage('请先加载音乐文件！', 'error');
            return;
        }

        this.reset();
        this.state.isPlaying = true;
        this.audio.play();
        document.getElementById('startBtn').disabled = true;
        document.getElementById('pauseBtn').disabled = false;
        this.gameLoop();
    }

    togglePause() {
        this.state.isPaused = !this.state.isPaused;
        if (this.state.isPaused) {
            this.audio.pause();
            document.getElementById('pauseBtn').textContent = '继续';
        } else {
            this.audio.play();
            document.getElementById('pauseBtn').textContent = '暂停';
            this.gameLoop();
        }
    }

    reset() {
        this.state.isPlaying = false;
        this.state.isPaused = false;
        this.state.score = 0;
        this.state.combo = 0;
        this.state.maxCombo = 0;
        this.state.accuracy = 100;
        this.state.judgments = { perfect: 0, great: 0, good: 0, miss: 0 };

        this.notes = [];
        this.currentTime = 0;
        this.noteIndex = 0;
        this.particles = [];
        this.activeDrags = [];
        this.keyPressed = [false, false, false, false];

        if (this.audio) {
            this.audio.pause();
            this.audio.currentTime = 0;
        }

        document.getElementById('startBtn').disabled = false;
        document.getElementById('pauseBtn').disabled = true;
        document.getElementById('pauseBtn').textContent = '暂停';

        this.updateUI();
    }

    gameLoop() {
        if (!this.state.isPlaying || this.state.isPaused) return;

        this.currentTime = this.audio.currentTime * 1000; // 转换为毫秒

        // 生成新音符
        this.spawnNotes();

        // 更新音符位置
        this.updateNotes();

        // 更新粒子效果
        this.updateParticles();

        // 渲染
        this.render();

        // 检查游戏是否结束
        if (this.audio.ended && this.notes.length === 0) {
            this.endGame();
            return;
        }

        requestAnimationFrame(() => this.gameLoop());
    }

    spawnNotes() {
        if (!this.chart || !this.chart.notes) return;

        // 提前生成时间 = 从顶部到判定线所需时间
        // 如果速度是400px/s，判定线在550px，则需要约1.4秒
        const spawnTime = 2000; // 提前2秒生成音符

        while (this.noteIndex < this.chart.notes.length) {
            const noteData = this.chart.notes[this.noteIndex];
            if (noteData.time <= this.currentTime + spawnTime) {
                const newNote = {
                    lane: noteData.lane,
                    time: noteData.time,
                    y: 0, // 从顶部开始
                    hit: false,
                    type: noteData.type || 'normal'
                };

                // 如果是drag音符，添加额外属性
                if (newNote.type === 'drag') {
                    newNote.duration = noteData.duration || 500; // 默认500ms
                    newNote.endTime = noteData.time + (noteData.duration || 500);
                    newNote.hitStart = false; // 是否击中了起始点
                    newNote.holding = false; // 是否正在按住
                }

                this.notes.push(newNote);
                this.noteIndex++;
            } else {
                break;
            }
        }
    }

    updateNotes() {
        const speed = this.config.noteSpeed * this.speedMultiplier;

        for (let i = this.notes.length - 1; i >= 0; i--) {
            const note = this.notes[i];

            // 计算音符应该在的位置
            // 音符应该在 time 时刻到达判定线
            // timeUntilHit = 音符时间 - 当前时间（正数表示还未到达，负数表示已过）
            const timeUntilHit = note.time - this.currentTime;

            // y位置 = 判定线位置 - (剩余时间 * 速度 / 1000)
            // 速度单位：像素/秒，所以除以1000转换为像素/毫秒
            note.y = this.config.judgmentLineY - (timeUntilHit * speed / 1000);

            // 处理Drag音符的按住状态
            if (note.type === 'drag' && note.hitStart && note.holding) {
                // 检查是否持续按住按键
                if (!this.keyPressed[note.lane]) {
                    // 提前松开，判定为miss
                    this.judge('miss');
                    this.showJudgment('MISS');
                    note.holding = false;
                    this.notes.splice(i, 1);
                } else if (this.currentTime >= note.endTime - 100) {
                    // 成功完成Drag - 允许提前100ms松开也给分
                    const holdAccuracy = Math.abs(this.currentTime - note.endTime);

                    let judgment = 'perfect';
                    if (holdAccuracy > 100) {
                        judgment = 'good';
                    } else if (holdAccuracy > 50) {
                        judgment = 'great';
                    }

                    this.judge(judgment);
                    this.showJudgment(judgment.toUpperCase());
                    this.createParticles(note.lane, judgment);
                    this.notes.splice(i, 1);
                }
            }

            // 检查是否错过音符
            if (note.type === 'normal') {
                if (note.y > this.config.judgmentLineY + 100 && !note.hit) {
                    this.judge('miss');
                    this.notes.splice(i, 1);
                }
            } else if (note.type === 'drag') {
                // Drag音符如果没有在判定窗口内开始，则miss
                if (note.y > this.config.judgmentLineY + 100 && !note.hitStart) {
                    this.judge('miss');
                    this.notes.splice(i, 1);
                }
            }
        }
    }

    updateParticles() {
        for (let i = this.particles.length - 1; i >= 0; i--) {
            const p = this.particles[i];
            p.x += p.vx;
            p.y += p.vy;
            p.vy += 0.3; // 重力
            p.alpha -= 0.02;
            p.size *= 0.98;

            if (p.alpha <= 0 || p.size <= 0.5) {
                this.particles.splice(i, 1);
            }
        }
    }

    handleKeyDown(event) {
        if (!this.state.isPlaying || this.state.isPaused) return;

        const key = event.key.toLowerCase();
        const laneIndex = this.config.keys.indexOf(key);

        if (laneIndex !== -1) {
            event.preventDefault();

            // 只有在键从未按下状态变为按下状态时才判定
            // 这样可以防止按住键时重复触发判定
            if (!this.keyPressed[laneIndex]) {
                this.laneEffects[laneIndex] = true;
                this.keyPressed[laneIndex] = true; // 记录按键状态
                this.checkHit(laneIndex);
            }
        }
    }

    handleKeyUp(event) {
        const key = event.key.toLowerCase();
        const laneIndex = this.config.keys.indexOf(key);

        if (laneIndex !== -1) {
            this.laneEffects[laneIndex] = false;
            this.keyPressed[laneIndex] = false; // 更新按键状态
        }
    }

    checkHit(laneIndex) {
        let closestNote = null;
        let closestDistance = Infinity;
        let closestIndex = -1;

        // 查找最接近判定线的音符
        for (let i = 0; i < this.notes.length; i++) {
            const note = this.notes[i];
            if (note.lane === laneIndex && !note.hit) {
                // 对于Drag音符，如果已经开始，则跳过
                if (note.type === 'drag' && note.hitStart) continue;

                const distance = Math.abs(note.y - this.config.judgmentLineY);
                if (distance < closestDistance) {
                    closestDistance = distance;
                    closestNote = note;
                    closestIndex = i;
                }
            }
        }

        if (closestNote) {
            // 判定时间差
            // 距离差转换为时间差：距离(px) / 速度(px/s) * 1000 = 时间(ms)
            // 注意：保留符号，正数表示音符在判定线上方（还未到达），负数表示已经过了
            const distanceToLine = closestNote.y - this.config.judgmentLineY;
            const distanceDiff = Math.abs(distanceToLine);
            const timeDiff = (distanceDiff / (this.config.noteSpeed * this.speedMultiplier)) * 1000;

            // Drag音符使用更宽松的判定窗口（大幅增加）
            const judgmentWindow = closestNote.type === 'drag' ?
                { perfect: 100, great: 150, good: 200 } :
                this.config.judgmentWindows;

            // 防作弊机制：如果音符还在判定线上方（还没到），且距离超过good窗口，判定为miss
            const tooEarlyThreshold = closestNote.type === 'drag' ? 300 : judgmentWindow.good;
            if (distanceToLine < 0 && timeDiff > tooEarlyThreshold) {
                // 提前太多，判定为miss
                this.judge('miss');
                this.showJudgment('TOO EARLY');
                closestNote.hit = true;
                this.notes.splice(closestIndex, 1);
                console.log(`抢拍miss: 提前${timeDiff.toFixed(1)}ms (阈值${tooEarlyThreshold}ms)`);
                return;
            }

            let judgment = 'miss';
            if (timeDiff <= judgmentWindow.perfect) {
                judgment = 'perfect';
            } else if (timeDiff <= judgmentWindow.great) {
                judgment = 'great';
            } else if (timeDiff <= judgmentWindow.good) {
                judgment = 'good';
            }

            // 调试信息
            if (closestNote.type === 'drag') {
                console.log(`Drag判定: 距离=${distanceDiff.toFixed(1)}px, 时间差=${timeDiff.toFixed(1)}ms, 判定=${judgment}`);
            }

            if (judgment !== 'miss') {
                if (closestNote.type === 'normal') {
                    // 普通音符，直接判定
                    this.judge(judgment);
                    closestNote.hit = true;
                    this.notes.splice(closestIndex, 1);
                    this.createParticles(laneIndex, judgment);
                } else if (closestNote.type === 'drag') {
                    // Drag音符，标记为开始，但不移除
                    closestNote.hitStart = true;
                    closestNote.holding = true;
                    closestNote.hit = true; // 标记为已击中，避免重复判定
                    // 显示开始判定反馈
                    this.showJudgment('HOLD');
                    this.createParticles(laneIndex, 'perfect');
                    console.log('Drag音符开始！');
                }
            } else if (closestNote.type === 'drag' && timeDiff <= 300) {
                // 即使miss，如果在300ms内，仍然激活drag（更宽容）
                console.log('宽容判定：激活Drag音符');
                closestNote.hitStart = true;
                closestNote.holding = true;
                closestNote.hit = true;
                this.showJudgment('HOLD');
                this.createParticles(laneIndex, 'good');
            }
        }
    }

    judge(judgment) {
        this.state.judgments[judgment]++;

        // 更新分数
        const scoreMap = { perfect: 300, great: 200, good: 100, miss: 0 };
        this.state.score += scoreMap[judgment];

        // 更新连击
        if (judgment !== 'miss') {
            this.state.combo++;
            if (this.state.combo > this.state.maxCombo) {
                this.state.maxCombo = this.state.combo;
            }
        } else {
            this.state.combo = 0;
        }

        // 更新准确率
        const total = Object.values(this.state.judgments).reduce((a, b) => a + b, 0);
        const weightedSum = this.state.judgments.perfect * 100 +
                           this.state.judgments.great * 80 +
                           this.state.judgments.good * 50;
        this.state.accuracy = total > 0 ? (weightedSum / (total * 100) * 100).toFixed(2) : 100;

        this.updateUI();
        this.showJudgment(judgment);
    }

    createParticles(laneIndex, judgment) {
        const x = laneIndex * this.config.laneWidth + this.config.laneWidth / 2;
        const y = this.config.judgmentLineY;
        const colorMap = {
            perfect: '#00ffff',
            great: '#00ff00',
            good: '#ffff00'
        };
        const color = colorMap[judgment];

        for (let i = 0; i < 15; i++) {
            this.particles.push({
                x: x,
                y: y,
                vx: (Math.random() - 0.5) * 8,
                vy: Math.random() * -10 - 5,
                size: Math.random() * 4 + 2,
                alpha: 1,
                color: color
            });
        }
    }

    showJudgment(judgment) {
        const feedback = document.getElementById('judgmentFeedback');
        feedback.textContent = judgment.toUpperCase();
        feedback.className = 'judgment-feedback ' + judgment;

        setTimeout(() => {
            feedback.className = 'judgment-feedback';
        }, 300);
    }

    updateUI() {
        document.getElementById('score').textContent = this.state.score;
        document.getElementById('combo').textContent = this.state.combo;
        document.getElementById('accuracy').textContent = this.state.accuracy + '%';
    }

    showMessage(message, type = 'success') {
        console.log(message);
        // 可以添加更好的消息显示方式
    }

    endGame() {
        this.state.isPlaying = false;
        document.getElementById('startBtn').disabled = false;
        document.getElementById('pauseBtn').disabled = true;

        const resultMessage = `
游戏结束！
最终得分: ${this.state.score}
最高连击: ${this.state.maxCombo}
准确率: ${this.state.accuracy}%
Perfect: ${this.state.judgments.perfect}
Great: ${this.state.judgments.great}
Good: ${this.state.judgments.good}
Miss: ${this.state.judgments.miss}
        `;
        alert(resultMessage);
    }

    render() {
        // 清空画布
        this.ctx.fillStyle = '#0a0e27';
        this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);

        // 绘制背景网格
        this.drawBackground();

        // 绘制轨道
        this.drawLanes();

        // 绘制判定线
        this.drawJudgmentLine();

        // 绘制音符
        this.drawNotes();

        // 绘制粒子效果
        this.drawParticles();

        // 绘制按键效果
        this.drawKeyEffects();
    }

    drawBackground() {
        this.ctx.strokeStyle = 'rgba(0, 255, 255, 0.05)';
        this.ctx.lineWidth = 1;

        // 水平线
        for (let y = 0; y < this.canvas.height; y += 30) {
            this.ctx.beginPath();
            this.ctx.moveTo(0, y);
            this.ctx.lineTo(this.canvas.width, y);
            this.ctx.stroke();
        }

        // 垂直线
        for (let x = 0; x < this.canvas.width; x += 30) {
            this.ctx.beginPath();
            this.ctx.moveTo(x, 0);
            this.ctx.lineTo(x, this.canvas.height);
            this.ctx.stroke();
        }
    }

    drawLanes() {
        for (let i = 0; i < this.config.lanes; i++) {
            const x = i * this.config.laneWidth;

            // 轨道边框
            this.ctx.strokeStyle = 'rgba(0, 255, 255, 0.5)';
            this.ctx.lineWidth = 2;
            this.ctx.strokeRect(x, 0, this.config.laneWidth, this.canvas.height);

            // 轨道发光效果
            if (this.laneEffects[i]) {
                const gradient = this.ctx.createLinearGradient(x, this.config.judgmentLineY - 100, x, this.config.judgmentLineY + 100);
                gradient.addColorStop(0, 'rgba(0, 255, 255, 0)');
                gradient.addColorStop(0.5, 'rgba(0, 255, 255, 0.3)');
                gradient.addColorStop(1, 'rgba(0, 255, 255, 0)');
                this.ctx.fillStyle = gradient;
                this.ctx.fillRect(x, 0, this.config.laneWidth, this.canvas.height);
            }
        }
    }

    drawJudgmentLine() {
        const y = this.config.judgmentLineY;

        // 发光效果
        const gradient = this.ctx.createLinearGradient(0, y - 10, 0, y + 10);
        gradient.addColorStop(0, 'rgba(255, 0, 255, 0)');
        gradient.addColorStop(0.5, 'rgba(255, 0, 255, 0.8)');
        gradient.addColorStop(1, 'rgba(255, 0, 255, 0)');
        this.ctx.fillStyle = gradient;
        this.ctx.fillRect(0, y - 10, this.canvas.width, 20);

        // 主线
        this.ctx.strokeStyle = '#ff00ff';
        this.ctx.lineWidth = 3;
        this.ctx.beginPath();
        this.ctx.moveTo(0, y);
        this.ctx.lineTo(this.canvas.width, y);
        this.ctx.stroke();

        // 闪烁效果
        const pulse = Math.sin(Date.now() / 200) * 0.3 + 0.7;
        this.ctx.strokeStyle = `rgba(255, 0, 255, ${pulse})`;
        this.ctx.lineWidth = 1;
        this.ctx.beginPath();
        this.ctx.moveTo(0, y - 5);
        this.ctx.lineTo(this.canvas.width, y - 5);
        this.ctx.moveTo(0, y + 5);
        this.ctx.lineTo(this.canvas.width, y + 5);
        this.ctx.stroke();
    }

    drawNotes() {
        for (const note of this.notes) {
            if (note.type === 'drag') {
                this.drawDragNote(note);
            } else {
                this.drawNormalNote(note);
            }
        }
    }

    drawNormalNote(note) {
        const x = note.lane * this.config.laneWidth;
        const y = note.y;

        switch (this.noteSkin) {
            case 'bar':
                this.drawBarNote(x, y);
                break;
            case 'circle':
                this.drawCircleNote(x, y);
                break;
            case 'arrow':
                this.drawArrowNote(x, y);
                break;
            default:
                this.drawBarNote(x, y);
        }
    }

    // 条型音符
    drawBarNote(x, y) {
        const gradient = this.ctx.createLinearGradient(x, y, x + this.config.laneWidth, y);
        gradient.addColorStop(0, '#00ffff');
        gradient.addColorStop(0.5, '#00ff88');
        gradient.addColorStop(1, '#00ffff');

        this.ctx.fillStyle = gradient;
        this.ctx.fillRect(x + 5, y, this.config.laneWidth - 10, this.config.noteHeight);

        // 音符边框
        this.ctx.strokeStyle = '#ffffff';
        this.ctx.lineWidth = 2;
        this.ctx.strokeRect(x + 5, y, this.config.laneWidth - 10, this.config.noteHeight);

        // 发光效果
        this.ctx.shadowBlur = 10;
        this.ctx.shadowColor = '#00ffff';
        this.ctx.strokeRect(x + 5, y, this.config.laneWidth - 10, this.config.noteHeight);
        this.ctx.shadowBlur = 0;
    }

    // 圆形音符
    drawCircleNote(x, y) {
        const centerX = x + this.config.laneWidth / 2;
        const centerY = y + this.config.noteHeight / 2;
        // 增大圆形半径，使用轨道宽度的80%作为直径
        const radius = (this.config.laneWidth * 0.8) / 2;

        // 外圈渐变
        const gradient = this.ctx.createRadialGradient(centerX, centerY, radius * 0.3, centerX, centerY, radius);
        gradient.addColorStop(0, '#00ffff');
        gradient.addColorStop(0.7, '#00ff88');
        gradient.addColorStop(1, 'rgba(0, 255, 255, 0.3)');

        this.ctx.fillStyle = gradient;
        this.ctx.beginPath();
        this.ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
        this.ctx.fill();

        // 外圈边框
        this.ctx.strokeStyle = '#ffffff';
        this.ctx.lineWidth = 3;
        this.ctx.beginPath();
        this.ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
        this.ctx.stroke();

        // 内圈
        this.ctx.fillStyle = '#00ffff';
        this.ctx.beginPath();
        this.ctx.arc(centerX, centerY, radius * 0.4, 0, Math.PI * 2);
        this.ctx.fill();

        // 发光效果
        this.ctx.shadowBlur = 20;
        this.ctx.shadowColor = '#00ffff';
        this.ctx.strokeStyle = '#00ffff';
        this.ctx.lineWidth = 2;
        this.ctx.beginPath();
        this.ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
        this.ctx.stroke();
        this.ctx.shadowBlur = 0;
    }

    // 箭头型音符
    drawArrowNote(x, y) {
        const centerX = x + this.config.laneWidth / 2;
        const arrowHeight = this.config.noteHeight * 2;
        const arrowWidth = this.config.laneWidth - 10;

        // 绘制箭头形状
        this.ctx.beginPath();
        this.ctx.moveTo(centerX, y); // 顶点
        this.ctx.lineTo(x + 5, y + arrowHeight * 0.6); // 左上
        this.ctx.lineTo(x + arrowWidth * 0.35, y + arrowHeight * 0.6); // 左中
        this.ctx.lineTo(x + arrowWidth * 0.35, y + arrowHeight); // 左下
        this.ctx.lineTo(x + arrowWidth * 0.65, y + arrowHeight); // 右下
        this.ctx.lineTo(x + arrowWidth * 0.65, y + arrowHeight * 0.6); // 右中
        this.ctx.lineTo(x + 5 + arrowWidth, y + arrowHeight * 0.6); // 右上
        this.ctx.closePath();

        // 渐变填充
        const gradient = this.ctx.createLinearGradient(centerX, y, centerX, y + arrowHeight);
        gradient.addColorStop(0, '#00ffff');
        gradient.addColorStop(0.6, '#00ff88');
        gradient.addColorStop(1, '#00cc88');

        this.ctx.fillStyle = gradient;
        this.ctx.fill();

        // 边框
        this.ctx.strokeStyle = '#ffffff';
        this.ctx.lineWidth = 2;
        this.ctx.stroke();

        // 发光效果
        this.ctx.shadowBlur = 12;
        this.ctx.shadowColor = '#00ffff';
        this.ctx.stroke();
        this.ctx.shadowBlur = 0;
    }

    drawDragNote(note) {
        const x = note.lane * this.config.laneWidth;
        const y = note.y;
        const speed = this.config.noteSpeed * this.speedMultiplier;

        // 计算Drag长度：duration(ms) * speed(px/s) / 1000 = length(px)
        const dragLength = (note.duration * speed) / 1000;
        // 修正：尾部应该在头部上方（因为音符从上往下掉）
        const endY = y - dragLength;

        // 绘制拖尾（从尾部到头部的长条）
        const tailGradient = this.ctx.createLinearGradient(x, endY, x, y);

        if (note.hitStart && note.holding) {
            // 正在按住时显示金色
            tailGradient.addColorStop(0, 'rgba(255, 215, 0, 0.8)');
            tailGradient.addColorStop(1, 'rgba(255, 215, 0, 0.3)');
        } else {
            // 未按住时显示紫色渐变
            tailGradient.addColorStop(0, 'rgba(255, 0, 255, 0.6)');
            tailGradient.addColorStop(1, 'rgba(128, 0, 255, 0.3)');
        }

        this.ctx.fillStyle = tailGradient;
        this.ctx.fillRect(x + 5, endY, this.config.laneWidth - 10, dragLength);

        // 绘制拖尾边框
        this.ctx.strokeStyle = note.hitStart && note.holding ? '#ffd700' : '#ff00ff';
        this.ctx.lineWidth = 2;
        this.ctx.strokeRect(x + 5, endY, this.config.laneWidth - 10, dragLength);

        // 根据皮肤绘制起始点和结束点
        switch (this.noteSkin) {
            case 'bar':
                this.drawDragBarEnds(x, y, endY, note);
                break;
            case 'circle':
                this.drawDragCircleEnds(x, y, endY, note);
                break;
            case 'arrow':
                this.drawDragArrowEnds(x, y, endY, note);
                break;
            default:
                this.drawDragBarEnds(x, y, endY, note);
        }

        // 发光效果
        if (note.hitStart && note.holding) {
            this.ctx.shadowBlur = 15;
            this.ctx.shadowColor = '#ffd700';
            this.ctx.strokeRect(x + 5, endY, this.config.laneWidth - 10, dragLength);
            this.ctx.shadowBlur = 0;
        }
    }

    drawDragBarEnds(x, y, endY, note) {
        // 绘制起始点（头部，在下方靠近判定线）
        const headGradient = this.ctx.createLinearGradient(x, y, x + this.config.laneWidth, y);
        headGradient.addColorStop(0, '#ff00ff');
        headGradient.addColorStop(0.5, '#ff88ff');
        headGradient.addColorStop(1, '#ff00ff');

        this.ctx.fillStyle = headGradient;
        this.ctx.fillRect(x + 5, y, this.config.laneWidth - 10, this.config.noteHeight);

        // 起始点边框
        this.ctx.strokeStyle = '#ffffff';
        this.ctx.lineWidth = 2;
        this.ctx.strokeRect(x + 5, y, this.config.laneWidth - 10, this.config.noteHeight);

        // 绘制结束点（尾部标记，在上方远离判定线）
        this.ctx.fillStyle = note.hitStart && note.holding ? '#ffd700' : '#8800ff';
        this.ctx.fillRect(x + 5, endY, this.config.laneWidth - 10, this.config.noteHeight);
        this.ctx.strokeStyle = '#ffffff';
        this.ctx.strokeRect(x + 5, endY, this.config.laneWidth - 10, this.config.noteHeight);
    }

    drawDragCircleEnds(x, y, endY, note) {
        const centerX = x + this.config.laneWidth / 2;
        // 使用与普通圆形音符相同的半径比例
        const radius = (this.config.laneWidth * 0.8) / 2;

        // 起始圆
        const headGradient = this.ctx.createRadialGradient(centerX, y + this.config.noteHeight / 2, radius * 0.3, centerX, y + this.config.noteHeight / 2, radius);
        headGradient.addColorStop(0, '#ff00ff');
        headGradient.addColorStop(0.7, '#ff88ff');
        headGradient.addColorStop(1, 'rgba(255, 0, 255, 0.3)');

        this.ctx.fillStyle = headGradient;
        this.ctx.beginPath();
        this.ctx.arc(centerX, y + this.config.noteHeight / 2, radius, 0, Math.PI * 2);
        this.ctx.fill();

        this.ctx.strokeStyle = '#ffffff';
        this.ctx.lineWidth = 3;
        this.ctx.beginPath();
        this.ctx.arc(centerX, y + this.config.noteHeight / 2, radius, 0, Math.PI * 2);
        this.ctx.stroke();

        // 结束圆
        const endColor = note.hitStart && note.holding ? '#ffd700' : '#8800ff';

        // 添加渐变效果到结束圆
        const endGradient = this.ctx.createRadialGradient(centerX, endY + this.config.noteHeight / 2, radius * 0.3, centerX, endY + this.config.noteHeight / 2, radius);
        if (note.hitStart && note.holding) {
            endGradient.addColorStop(0, '#ffd700');
            endGradient.addColorStop(0.7, '#ffaa00');
            endGradient.addColorStop(1, 'rgba(255, 215, 0, 0.3)');
        } else {
            endGradient.addColorStop(0, '#8800ff');
            endGradient.addColorStop(0.7, '#aa00ff');
            endGradient.addColorStop(1, 'rgba(136, 0, 255, 0.3)');
        }

        this.ctx.fillStyle = endGradient;
        this.ctx.beginPath();
        this.ctx.arc(centerX, endY + this.config.noteHeight / 2, radius, 0, Math.PI * 2);
        this.ctx.fill();

        this.ctx.strokeStyle = '#ffffff';
        this.ctx.lineWidth = 3;
        this.ctx.beginPath();
        this.ctx.arc(centerX, endY + this.config.noteHeight / 2, radius, 0, Math.PI * 2);
        this.ctx.stroke();
    }

    drawDragArrowEnds(x, y, endY, note) {
        // 起始箭头（向下）
        const centerX = x + this.config.laneWidth / 2;
        const arrowWidth = this.config.laneWidth - 10;
        const arrowHeight = this.config.noteHeight * 1.5;

        this.ctx.beginPath();
        this.ctx.moveTo(centerX, y + arrowHeight); // 底部顶点
        this.ctx.lineTo(x + 5, y + arrowHeight * 0.4);
        this.ctx.lineTo(x + arrowWidth * 0.35, y + arrowHeight * 0.4);
        this.ctx.lineTo(x + arrowWidth * 0.35, y);
        this.ctx.lineTo(x + arrowWidth * 0.65, y);
        this.ctx.lineTo(x + arrowWidth * 0.65, y + arrowHeight * 0.4);
        this.ctx.lineTo(x + 5 + arrowWidth, y + arrowHeight * 0.4);
        this.ctx.closePath();

        const headGradient = this.ctx.createLinearGradient(centerX, y, centerX, y + arrowHeight);
        headGradient.addColorStop(0, '#ff00ff');
        headGradient.addColorStop(1, '#ff88ff');
        this.ctx.fillStyle = headGradient;
        this.ctx.fill();

        this.ctx.strokeStyle = '#ffffff';
        this.ctx.lineWidth = 2;
        this.ctx.stroke();

        // 结束箭头（向上）
        this.ctx.beginPath();
        this.ctx.moveTo(centerX, endY - arrowHeight); // 顶部顶点
        this.ctx.lineTo(x + 5, endY - arrowHeight * 0.6);
        this.ctx.lineTo(x + arrowWidth * 0.35, endY - arrowHeight * 0.6);
        this.ctx.lineTo(x + arrowWidth * 0.35, endY);
        this.ctx.lineTo(x + arrowWidth * 0.65, endY);
        this.ctx.lineTo(x + arrowWidth * 0.65, endY - arrowHeight * 0.6);
        this.ctx.lineTo(x + 5 + arrowWidth, endY - arrowHeight * 0.6);
        this.ctx.closePath();

        const endColor = note.hitStart && note.holding ? '#ffd700' : '#8800ff';
        this.ctx.fillStyle = endColor;
        this.ctx.fill();

        this.ctx.strokeStyle = '#ffffff';
        this.ctx.stroke();
    }

    drawParticles() {
        for (const p of this.particles) {
            this.ctx.fillStyle = p.color + Math.floor(p.alpha * 255).toString(16).padStart(2, '0');
            this.ctx.beginPath();
            this.ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
            this.ctx.fill();
        }
    }

    drawKeyEffects() {
        const keyHints = document.querySelectorAll('.key-hint');
        keyHints.forEach((hint, index) => {
            if (this.laneEffects[index]) {
                hint.classList.add('active');
            } else {
                hint.classList.remove('active');
            }
        });
    }

    // ==================== 服务器交互方法 ====================

    async loadSongList() {
        try {
            const response = await fetch(`${this.apiBaseUrl}/songs`);
            const data = await response.json();

            if (data.success) {
                this.serverSongs = data.songs;
                this.updateSongSelect();
                console.log(`加载了 ${this.serverSongs.length} 首乐曲`);
            } else {
                console.error('加载乐曲列表失败:', data.error);
            }
        } catch (error) {
            console.warn('无法连接服务器，请使用本地文件:', error.message);
            // 清空乐曲列表
            this.serverSongs = [];
            this.updateSongSelect();
        }
    }

    updateSongSelect() {
        const select = document.getElementById('songSelect');

        // 清空现有选项（保留第一个占位选项）
        while (select.options.length > 1) {
            select.remove(1);
        }

        // 添加乐曲选项
        this.serverSongs.forEach(song => {
            const option = document.createElement('option');
            option.value = song.id;
            option.textContent = `${song.title} - ${song.artist} [${song.difficulty} Lv.${song.level}]`;
            select.appendChild(option);
        });
    }

    async selectSong(event) {
        const songId = parseInt(event.target.value);

        if (!songId) {
            // 清空选择
            this.selectedSong = null;
            this.chart = null;
            this.audio = null;
            document.getElementById('songInfo').style.display = 'none';
            return;
        }

        // 查找乐曲信息
        const song = this.serverSongs.find(s => s.id === songId);
        if (!song) {
            console.error('乐曲不存在');
            return;
        }

        this.selectedSong = song;

        // 显示乐曲信息
        document.getElementById('songInfo').style.display = 'flex';
        document.getElementById('selectedSongTitle').textContent = song.title;
        document.getElementById('selectedSongArtist').textContent = `艺术家: ${song.artist}`;
        document.getElementById('selectedSongDifficulty').textContent = `${song.difficulty} Lv.${song.level}`;

        // 加载谱面和音频
        await this.loadSongFromServer(songId);
    }

    async loadSongFromServer(songId) {
        try {
            this.showMessage('正在加载乐曲...');

            // 加载谱面
            const chartResponse = await fetch(`${this.apiBaseUrl}/songs/${songId}/chart`);
            const chartData = await chartResponse.json();

            if (!chartData.success) {
                throw new Error(chartData.error || '谱面加载失败');
            }

            this.chart = chartData.chart;
            console.log('谱面加载成功:', this.chart.metadata?.title || '未知标题');

            // 加载音频
            const audioUrl = `${this.apiBaseUrl}/songs/${songId}/audio`;
            this.audio = new Audio(audioUrl);

            // 检查音频格式支持
            const song = this.serverSongs.find(s => s.id === songId);
            if (song && song.audio_file) {
                const ext = song.audio_file.split('.').pop().toLowerCase();
                const canPlay = this.audio.canPlayType(`audio/${ext}`);

                if (!canPlay || canPlay === 'no') {
                    console.warn(`⚠️ 浏览器可能不支持 ${ext} 格式`);
                    this.showMessage(`警告: 浏览器可能不支持 ${ext.toUpperCase()} 格式，建议使用 MP3/OGG/WAV`, 'warning');
                } else if (canPlay === 'maybe') {
                    console.warn(`⚠️ 浏览器对 ${ext} 格式支持不确定`);
                }
            }

            await new Promise((resolve, reject) => {
                // 增加超时时间到30秒（FLAC文件较大）
                const timeout = setTimeout(() => {
                    reject(new Error('音频加载超时（30秒）- 文件可能太大或格式不支持'));
                }, 30000);

                this.audio.addEventListener('loadeddata', () => {
                    clearTimeout(timeout);
                    resolve();
                });

                this.audio.addEventListener('canplaythrough', () => {
                    clearTimeout(timeout);
                    resolve();
                });

                this.audio.addEventListener('error', (e) => {
                    clearTimeout(timeout);
                    let errorMsg = '音频加载失败';
                    if (this.audio.error) {
                        switch(this.audio.error.code) {
                            case MediaError.MEDIA_ERR_ABORTED:
                                errorMsg = '音频加载被中止';
                                break;
                            case MediaError.MEDIA_ERR_NETWORK:
                                errorMsg = '网络错误';
                                break;
                            case MediaError.MEDIA_ERR_DECODE:
                                errorMsg = '音频解码失败 - 格式不支持或文件损坏';
                                break;
                            case MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED:
                                errorMsg = '音频格式不支持或文件不存在';
                                break;
                        }
                    }
                    reject(new Error(errorMsg));
                });

                this.audio.load();
            });

            console.log('音频加载成功');
            this.showMessage('乐曲加载完成，可以开始游戏！');

        } catch (error) {
            console.error('加载乐曲失败:', error);
            this.showMessage('加载乐曲失败: ' + error.message, 'error');
            this.chart = null;
            this.audio = null;
        }
    }
}

// 初始化游戏
window.addEventListener('DOMContentLoaded', () => {
    new RhythmGame();
});
